/**
 * 审计中间件
 * EndoSight-UC 医疗AI系统
 *
 * 自动拦截和记录用户操作、数据访问和系统事件
 */

import structuredLogger, { AuditEventType, generateCorrelationId } from '../utils/structuredLogger.js';
import auditService from '../services/auditService.js';
import { detectPHI } from '../utils/structuredLogger.js';

/**
 * 生成请求关联ID
 */
const generateRequestId = () => {
  return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
};

/**
 * 审计中间件
 */
export const auditMiddleware = (req, res, next) => {
  const startTime = Date.now();
  const requestId = generateRequestId();
  const originalSend = res.send;
  const originalJson = res.json;

  // 为请求添加审计上下文
  req.auditContext = {
    requestId,
    startTime,
    userId: req.user?.doctor_id,
    sessionId: req.session?.id,
    ipAddress: req.ip,
    userAgent: req.get('User-Agent'),
    method: req.method,
    originalUrl: req.originalUrl || req.url,
    params: { ...req.params },
    query: { ...req.query }
  };

  // 记录请求开始
  structuredLogger.info('请求开始', {
    correlationId: requestId,
    request: {
      method: req.method,
      url: req.originalUrl || req.url,
      ip: req.ip,
      userAgent: req.get('User-Agent')
    },
    user: req.user ? {
      userId: req.user.doctor_id,
      username: req.user.username,
      role: req.user.role
    } : null
  });

  // 重写响应方法以捕获响应数据
  let responseData = null;
  let statusCode = null;

  res.send = function(data) {
    responseData = data;
    statusCode = res.statusCode;
    return originalSend.call(this, data);
  };

  res.json = function(data) {
    responseData = data;
    statusCode = res.statusCode;
    return originalJson.call(this, data);
  };

  // 监听响应结束
  res.on('finish', async () => {
    const duration = Date.now() - startTime;
    const route = req.route ? req.route.path : req.path;

    try {
      // 记录HTTP请求完成
      structuredLogger.httpRequest(req, res, duration, {
        correlationId: requestId,
        userId: req.user?.doctor_id
      });

      // 执行路由特定的审计
      await performRouteSpecificAudit(req, res, {
        requestId,
        duration,
        route,
        statusCode,
        responseData
      });

      // 检查安全事件
      await checkSecurityEvents(req, res, {
        requestId,
        duration,
        statusCode
      });

    } catch (error) {
      structuredLogger.error('审计中间件执行失败', error, {
        requestId,
        method: req.method,
        url: req.originalUrl
      });
    }
  });

  // 监听响应错误
  res.on('error', async (error) => {
    try {
      structuredLogger.error('响应错误', error, {
        correlationId: requestId,
        method: req.method,
        url: req.originalUrl
      });

      // 记录错误审计
      await auditService.insertAuditLog({
        level: 'error',
        message: `HTTP响应错误: ${req.method} ${req.originalUrl}`,
        correlationId: requestId,
        userId: req.user?.doctor_id,
        action: 'http_error',
        resourceType: 'http_request',
        logData: JSON.stringify({
          method: req.method,
          url: req.originalUrl,
          error: error.message,
          statusCode: res.statusCode
        })
      });
    } catch (auditError) {
      structuredLogger.error('错误审计记录失败', auditError);
    }
  });

  next();
};

/**
 * 执行路由特定的审计
 */
const performRouteSpecificAudit = async (req, res, auditData) => {
  const { route, statusCode, responseData } = auditData;
  const userId = req.user?.doctor_id;
  const sessionId = req.session?.id;

  try {
    // 患者相关操作审计
    if (route.includes('/patients')) {
      try {
        await auditPatientOperations(req, res, auditData);
      } catch (error) {
        structuredLogger.error('患者操作审计失败', error);
      }
    }

    // 评分相关操作审计
    else if (route.includes('/scoring')) {
      try {
        await auditScoringOperations(req, res, auditData);
      } catch (error) {
        structuredLogger.error('评分操作审计失败', error);
      }
    }

    // 认证相关操作审计
    else if (route.includes('/auth')) {
      try {
        await auditAuthOperations(req, res, auditData);
      } catch (error) {
        structuredLogger.error('认证操作审计失败', error);
      }
    }

    // 文件相关操作审计
    else if (route.includes('/upload') || route.includes('/files')) {
      try {
        await auditFileOperations(req, res, auditData);
      } catch (error) {
        structuredLogger.error('文件操作审计失败', error);
      }
    }

    // 系统配置相关操作审计
    else if (route.includes('/admin') || route.includes('/config')) {
      try {
        await auditSystemOperations(req, res, auditData);
      } catch (error) {
        structuredLogger.error('系统操作审计失败', error);
      }
    }

    // 数据导出相关操作审计
    else if (route.includes('/export') || route.includes('/download')) {
      try {
        await auditDataExportOperations(req, res, auditData);
      } catch (error) {
        structuredLogger.error('数据导出操作审计失败', error);
      }
    }

    // 检测PHI数据访问
    if (responseData && typeof responseData === 'object') {
      const phiDetected = detectPHI(responseData);
      if (phiDetected.length > 0) {
        await auditService.logMedicalDataAccess(
          userId,
          sessionId,
          extractPatientIdFromData(responseData),
          'api_response',
          'view',
          `API访问包含PHI数据: ${route}`,
          {
            phiDetected,
            route,
            method: req.method,
            auditData
          }
        );
      }
    }

  } catch (error) {
    structuredLogger.error('路由特定审计失败', error, {
      route,
      method: req.method,
      userId
    });
  }
};

/**
 * 审计患者相关操作
 */
const auditPatientOperations = async (req, res, auditData) => {
  const { route, statusCode, responseData } = auditData;
  const userId = req.user?.doctor_id;
  const sessionId = req.session?.id;

  try {
    const patientId = req.params.patientId || req.params.id ||
                    responseData?.data?.patient_id ||
                    responseData?.patient_id;

    // 患者创建
    if (req.method === 'POST' && statusCode === 201) {
      await auditService.audit(
        AuditEventType.PATIENT_CREATE,
        `创建患者记录: ${patientId}`,
        { type: 'patient', id: patientId },
        userId,
        {
          metadata: {
            route,
            patientData: sanitizeDataForAudit(responseData?.data)
          }
        }
      );

      if (patientId) {
        await auditService.logMedicalDataAccess(
          userId,
          sessionId,
          patientId,
          'patient_record',
          'create',
          '创建患者基本信息',
          {
            consentVerified: true,
            consentType: 'treatment'
          }
        );
      }
    }

    // 患者查看
    else if (req.method === 'GET' && statusCode === 200) {
      await auditService.audit(
        AuditEventType.PATIENT_VIEW,
        `查看患者信息: ${patientId}`,
        { type: 'patient', id: patientId },
        userId,
        {
          metadata: { route }
        }
      );

      if (patientId) {
        await auditService.logMedicalDataAccess(
          userId,
          sessionId,
          patientId,
          'patient_record',
          'view',
          '查看患者基本信息',
          {
            consentVerified: true,
            consentType: 'treatment'
          }
        );
      }
    }

    // 患者更新
    else if (req.method === 'PUT' || req.method === 'PATCH') {
      await auditService.audit(
        AuditEventType.PATIENT_UPDATE,
        `更新患者信息: ${patientId}`,
        { type: 'patient', id: patientId },
        userId,
        {
          metadata: {
            route,
            updateData: sanitizeDataForAudit(req.body)
          }
        }
      );

      if (patientId) {
        await auditService.logMedicalDataAccess(
          userId,
          sessionId,
          patientId,
          'patient_record',
          'update',
          '更新患者基本信息',
          {
            consentVerified: true,
            consentType: 'treatment',
            dataBefore: responseData?.previousData,
            dataAfter: req.body
          }
        );
      }
    }

    // 患者删除
    else if (req.method === 'DELETE' && statusCode === 200) {
      await auditService.audit(
        AuditEventType.PATIENT_DELETE,
        `删除患者记录: ${patientId}`,
        { type: 'patient', id: patientId },
        userId,
        {
          metadata: { route }
        }
      );
    }

  } catch (error) {
    structuredLogger.error('患者操作审计失败', error);
  }
};

/**
 * 审计评分相关操作
 */
const auditScoringOperations = async (req, res, auditData) => {
  const { route, statusCode, responseData } = auditData;
  const userId = req.user?.doctor_id;
  const sessionId = req.session?.id;

  try {
    // 安全地获取taskId，避免undefined错误
    let taskId = null;
    if (req.params && (req.params.taskId || req.params.id)) {
      taskId = req.params.taskId || req.params.id;
    } else if (responseData && responseData.data && responseData.data.task_id) {
      taskId = responseData.data.task_id;
    } else if (responseData && responseData.task_id) {
      taskId = responseData.task_id;
    }

    // 安全地获取patientId
    let patientId = null;
    if (responseData && responseData.data && responseData.data.patient_id) {
      patientId = responseData.data.patient_id;
    } else if (req.body && req.body.patient_id) {
      patientId = req.body.patient_id;
    }

    // 评分任务创建 - 只在taskId存在时进行审计
    if (route.includes('/scoring') && req.method === 'POST' && statusCode === 201 && taskId) {
      await auditService.audit(
        AuditEventType.SCORING_TASK_CREATE,
        `创建评分任务: ${taskId}`,
        { type: 'scoring_task', id: taskId },
        userId,
        {
          metadata: {
            route,
            taskData: sanitizeDataForAudit(req.body)
          }
        }
      );

      if (patientId) {
        await auditService.logMedicalDataAccess(
          userId,
          sessionId,
          patientId,
          'scoring_task',
          'create',
          '创建UCEIS评分任务',
          {
            consentVerified: true,
            consentType: 'treatment'
          }
        );
      }
    }

    // 评分结果创建 - 安全地获取result_id
    else if (route.includes('/results') && req.method === 'POST' && statusCode === 201) {
      const resultId = responseData?.data?.result_id || responseData?.result_id;

      if (resultId) {
        await auditService.audit(
          AuditEventType.SCORING_RESULT_CREATE,
          `创建评分结果: ${resultId}`,
          { type: 'scoring_result', id: resultId },
          userId,
          {
            metadata: {
              route,
              resultData: sanitizeDataForAudit(responseData?.data)
            }
          }
        );
      }

      if (patientId && taskId) {
        await auditService.logMedicalDataAccess(
          userId,
          sessionId,
          patientId,
          'scoring_result',
          'create',
          '创建UCEIS评分结果',
          {
            consentVerified: true,
            consentType: 'treatment',
            taskId
          }
        );
      }
    }

    // 评分结果查看
    else if (route.includes('/results') && req.method === 'GET' && statusCode === 200) {
      await auditService.audit(
        AuditEventType.SCORING_RESULT_VIEW,
        `查看评分结果: ${responseData?.data?.result_id}`,
        { type: 'scoring_result', id: responseData?.data?.result_id },
        userId,
        {
          metadata: { route }
        }
      );
    }

  } catch (error) {
    structuredLogger.error('评分操作审计失败', error);
  }
};

/**
 * 审计认证相关操作
 */
const auditAuthOperations = async (req, res, auditData) => {
  const { route, statusCode, responseData } = auditData;
  const ipAddress = req.ip;
  const userAgent = req.get('User-Agent');

  try {
    // 登录成功
    if (route.includes('/login') && statusCode === 200) {
      const userId = responseData?.data?.doctor_id || responseData?.doctor_id;
      const sessionId = responseData?.sessionId || generateCorrelationId();

      await auditService.logUserLogin(
        userId,
        'password',
        ipAddress,
        userAgent,
        true,
        {
          sessionId,
          loginTime: new Date().toISOString()
        }
      );
    }

    // 登录失败
    else if (route.includes('/login') && statusCode >= 400) {
      await auditService.logUserLogin(
        req.body?.username || 'unknown',
        'password',
        ipAddress,
        userAgent,
        false,
        {
          reason: responseData?.message || 'Authentication failed',
          loginTime: new Date().toISOString()
        }
      );
    }

    // 登出
    else if (route.includes('/logout') && statusCode === 200) {
      const userId = req.user?.doctor_id;
      const sessionId = req.session?.id;

      await auditService.logUserLogout(userId, sessionId, 'user_initiated');
    }

    // 注册
    else if (route.includes('/register') && statusCode === 201) {
      const userId = responseData?.data?.doctor_id;

      await auditService.audit(
        AuditEventType.USER_REGISTER,
        `用户注册: ${userId}`,
        { type: 'user', id: userId },
        userId,
        {
          metadata: {
            ipAddress,
            userAgent,
            registrationTime: new Date().toISOString()
          }
        }
      );
    }

  } catch (error) {
    structuredLogger.error('认证操作审计失败', error);
  }
};

/**
 * 审计文件相关操作
 */
const auditFileOperations = async (req, res, auditData) => {
  const { route, statusCode, responseData } = auditData;
  const userId = req.user?.doctor_id;
  const sessionId = req.session?.id;

  try {
    // 文件上传
    if (route.includes('/upload') && req.method === 'POST') {
      if (statusCode === 200 || statusCode === 201) {
        const fileInfo = req.file || responseData?.data;

        await auditService.logFileOperation(userId, sessionId, 'upload', {
          fileName: fileInfo?.originalname || fileInfo?.filename,
          filePath: fileInfo?.path,
          fileType: fileInfo?.mimetype,
          fileSize: fileInfo?.size,
          fileHash: fileInfo?.validationResult?.fileHash,
          medicalImage: true, // 假设上传的都是医疗图像
          patientId: req.body?.patient_id,
          taskId: req.body?.task_id,
          validationResult: fileInfo?.validationResult,
          storageLocation: fileInfo?.path
        });
      }
    }

    // 文件删除
    else if (req.method === 'DELETE' && statusCode === 200) {
      const fileData = {
        fileName: req.params.filename || 'unknown',
        medicalImage: true,
        patientId: req.body?.patient_id
      };

      await auditService.logFileOperation(userId, sessionId, 'delete', fileData);
    }

  } catch (error) {
    structuredLogger.error('文件操作审计失败', error);
  }
};

/**
 * 审计系统操作
 */
const auditSystemOperations = async (req, res, auditData) => {
  const { route, statusCode } = auditData;
  const userId = req.user?.doctor_id;

  try {
    // 系统配置变更
    if (req.method === 'PUT' || req.method === 'PATCH') {
      await auditService.audit(
        AuditEventType.SYSTEM_CONFIG_CHANGE,
        `系统配置变更: ${route}`,
        { type: 'system_config', route },
        userId,
        {
          metadata: {
            route,
            method: req.method,
            configData: sanitizeDataForAudit(req.body)
          }
        }
      );
    }

  } catch (error) {
    structuredLogger.error('系统操作审计失败', error);
  }
};

/**
 * 审计数据导出操作
 */
const auditDataExportOperations = async (req, res, auditData) => {
  const { route, statusCode, responseData } = auditData;
  const userId = req.user?.doctor_id;
  const sessionId = req.session?.id;

  try {
    // 数据导出
    if (route.includes('/export') && req.method === 'POST') {
      if (statusCode === 200) {
        const exportData = {
          exportType: req.body?.type || 'unknown',
          exportFormat: req.body?.format || 'json',
          dataScope: req.body?.scope,
          recordCount: responseData?.data?.count || 0,
          fileSize: responseData?.data?.size || 0,
          exportFilePath: responseData?.data?.filePath,
          includesPhi: req.body?.includePhi || false,
          phiCount: responseData?.data?.phiCount || 0,
          consentVerified: req.body?.consentVerified || false,
          purpose: req.body?.purpose || 'unknown',
          recipientInfo: req.body?.recipientInfo,
          approved: req.body?.approved || false,
          approvedBy: req.body?.approvedBy
        };

        await auditService.logDataExport(userId, sessionId, exportData);
      }
    }

  } catch (error) {
    structuredLogger.error('数据导出审计失败', error);
  }
};

/**
 * 检查安全事件
 */
const checkSecurityEvents = async (req, res, auditData) => {
  const { statusCode, requestId } = auditData;
  const userId = req.user?.doctor_id;
  const ipAddress = req.ip;

  try {
    // 检查认证失败
    if (statusCode === 401) {
      await auditService.logUserLogin(
        req.body?.username || 'unknown',
        'api_token',
        ipAddress,
        req.get('User-Agent'),
        false,
        {
          requestId,
          reason: 'API认证失败',
          endpoint: req.originalUrl
        }
      );

      // 记录安全事件
      structuredLogger.security(
        'authentication_failure',
        `API认证失败: ${req.originalUrl}`,
        'medium',
        {
          userId,
          ipAddress,
          requestId,
          endpoint: req.originalUrl
        }
      );
    }

    // 检查授权失败
    else if (statusCode === 403) {
      structuredLogger.security(
        'authorization_failure',
        `API授权失败: ${req.originalUrl}`,
        'medium',
        {
          userId,
          ipAddress,
          requestId,
          endpoint: req.originalUrl,
          requiredPermissions: req.requiredPermissions
        }
      );

      await auditService.logComplianceViolation(
        userId,
        'unauthorized_access',
        'medium',
        `用户尝试访问未授权资源: ${req.originalUrl}`,
        {
          ipAddress,
          requestId,
          endpoint: req.originalUrl,
          requiredPermissions: req.requiredPermissions
        }
      );
    }

    // 检查可疑的请求模式
    await checkSuspiciousPatterns(req, auditData);

  } catch (error) {
    structuredLogger.error('安全事件检查失败', error);
  }
};

/**
 * 检查可疑请求模式
 */
const checkSuspiciousPatterns = async (req, auditData) => {
  const { requestId } = auditData;
  const userId = req.user?.doctor_id;
  const ipAddress = req.ip;

  try {
    // 检查异常大的请求体
    const contentLength = req.get('Content-Length');
    if (contentLength && parseInt(contentLength) > 50 * 1024 * 1024) { // 50MB
      structuredLogger.security(
        'large_request',
        `异常大的请求: ${contentLength} bytes`,
        'low',
        {
          userId,
          ipAddress,
          requestId,
          contentLength,
          endpoint: req.originalUrl
        }
      );
    }

    // 检查异常的User-Agent
    const userAgent = req.get('User-Agent');
    if (!userAgent || userAgent.length < 10) {
      structuredLogger.security(
        'suspicious_user_agent',
        `可疑的User-Agent: ${userAgent}`,
        'low',
        {
          userId,
          ipAddress,
          requestId,
          userAgent,
          endpoint: req.originalUrl
        }
      );
    }

  } catch (error) {
    structuredLogger.error('可疑模式检查失败', error);
  }
};

/**
 * 从数据中提取患者ID
 */
const extractPatientIdFromData = (data) => {
  if (!data || typeof data !== 'object') return null;

  // 直接字段查找
  if (data.patient_id) return data.patient_id;
  if (data.patientId) return data.patientId;

  // 嵌套数据查找
  if (data.data?.patient_id) return data.data.patient_id;
  if (data.data?.patientId) return data.data.patientId;

  return null;
};

/**
 * 清理数据用于审计（移除敏感信息）
 */
const sanitizeDataForAudit = (data) => {
  if (!data || typeof data !== 'object') return data;

  const sanitized = { ...data };

  // 移除密码等敏感字段
  delete sanitized.password;
  delete sanitized.token;
  delete sanitized.secret;
  delete sanitized.apiKey;

  // 脱敏其他敏感信息
  if (sanitized.email) {
    sanitized.email = sanitized.email.replace(/(.{2}).*@/, '***@');
  }

  return sanitized;
};

export default auditMiddleware;